﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Runtime;
using System.Runtime.Serialization;
using GeneratorLib.DB.Schemas;


namespace GeneratorLib.DB.Connectios
{

    [Serializable]
    public abstract class DBConnectionBase : IConnection, ISerializable
    {

        public int Ver
        {
            get;
            private set;
        }
        public string UID
        {
            get;
            private set;
        }
        public string Name { get; protected set; }
        public string ConnectStr { get; protected set; }
        public virtual string DBTypeMapping { get; protected set; }

        //DBParameter------------------------------------------------------
        public virtual string DbParamType { get; protected set; }
        public virtual string DbParamDbType { get; protected set; }
        public virtual string PreParameter { get; protected set; }
        //DBParameter------------------------------------------------------

        public abstract IDBProvider DBProvider { get; }

        protected List<TableInfo> tables;
        public List<TableInfo> Tables
        {
            get
            {
                if (tables == null)
                    FillTables();

                return tables;
            }
            private set
            {
                tables = value;
            }
        }

        protected List<Relation> relations;
        public List<Relation> Relations
        {
            get
            {
                if (relations == null)
                    return null;

                return relations;
            }
            set
            {
                relations = value;
            }
        }

        protected List<TableInfoAddin> tableAddins;
        public List<TableInfoAddin> TableAddins
        {
            get
            {
                if (tableAddins == null)
                    FillTableAddins();

                return tableAddins;
            }
            set
            {
                tableAddins = value;
            }
        }

        public DBConnectionBase(string name, string connectStr)
        {
            this.Ver = 2;
            this.UID = Guid.NewGuid().ToString();
            this.Name = name;
            this.ConnectStr = connectStr;
            Relations = new List<Relation>();
            //TableAddins = new List<TableInfoAddin>();
        }

        public DBConnectionBase(SerializationInfo info, StreamingContext context)
        {
            int v = info.GetInt32("Ver");
            if (v == 0)
            {
                this.Ver = 1;
                this.UID = Guid.NewGuid().ToString();
            }
            else
            {
                this.UID = info.GetString("UID");
            }
            
            this.Name = info.GetString("Name");
            this.ConnectStr = info.GetString("ConnectStr");
            Relations = (List<Relation>)info.GetValue("Relations", typeof(List<Relation>));
            TableAddins = (List<TableInfoAddin>)info.GetValue("TableAddins", typeof(List<TableInfoAddin>));
        }

        public void SetName(string name)
        {
            this.Name = name;
        }

        public void SetConnectStr(string connectStr)
        {
            this.ConnectStr = connectStr;
        }

        public void Reset()
        {
            this.Tables = null;
        }

        public void AddRelation(Relation relation)
        {
            if (this.Relations.Contains(relation))
            {
                throw new Exception("relationship has existsed!");
            }
            Relations.Add(relation);
        }

        public void RemoveRelation(Relation relation)
        {
            Relations.Remove(relation);
        }

        public void ClearRelation()
        {
            Relations.Clear();
        }
        public void ClearRelation(TableInfo table)
        {
            while (true)
            {
                Relation r1 = this.Relations.Find(m => m.PrimaryTable.TableName.ToLower().CompareTo(table.TableName.ToLower()) == 0);
                Relation r2 = this.Relations.Find(m => m.ForeignTable.TableName.ToLower().CompareTo(table.TableName.ToLower()) == 0);
                if (r1 == null && r2 == null)
                {
                    break;
                }
                else
                {
                    if (r1 != null)
                        RemoveRelation(r1);

                    if (r2 != null)
                        RemoveRelation(r2);
                }
            }
        }


        public void AddTableAddin(TableInfoAddin tableAddin)
        {
            if (this.TableAddins.Contains(tableAddin))
            {
                this.TableAddins.Remove(tableAddin);
            }
            TableAddins.Add(tableAddin);
        }

        public void RemoveTableAddin(TableInfoAddin tableAddin)
        {
            TableAddins.Remove(tableAddin);
        }


        public TableInfo FindTable(string tableName)
        {
            return Tables.Find(m => m.TableName.ToLower().CompareTo(tableName.ToLower()) == 0);
        }

        public TableInfoAddin FindTableAddin(string tableName)
        {
            TableInfoAddin tAddin= TableAddins.Find(m => m.TableName.ToLower().CompareTo(tableName.ToLower()) == 0);
            if (tAddin == null)
            {
                tAddin = new TableInfoAddin(tableName);
                AddTableAddin(tAddin);
            }
            return tAddin;
        }

        public virtual List<FieldInfo> GetTableField(TableInfo table)
        {
            return null;
        }

        public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("Ver", this.Ver);
            info.AddValue("UID", this.UID);
            info.AddValue("Name", Name);
            info.AddValue("ConnectStr", ConnectStr);
            info.AddValue("Relations", Relations);
            info.AddValue("TableAddins", TableAddins);
        }

        protected virtual void FillTables()
        {
            
        }

        protected virtual void FillTableAddins()
        {
            
        }

        public override int GetHashCode()
        {
            return this.UID.GetHashCode();
        }
        public override bool Equals(object obj)
        {
            DBConnectionBase db = obj as DBConnectionBase;
            if (db == null) return false;
            return db.UID.Equals(this.UID);
        }

    }








}
